'use client';

import type { TMetadata } from '@/types';
import type {
  IPagination,
  IPost,
  IQueryParams,
  ISectionClient,
  ISectionDetails,
  ISectionGroup,
  ITag,
} from '@/interfaces';
import useUser from '@/hooks/useUser';
import {
  type ChangeEvent,
  type FormEvent,
  type MouseEvent,
  useEffect,
  useState,
} from 'react';
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
import {
  clientQueryAllPost,
  clientQueryAllSection,
  clientQuerySectionDetailsById,
  queryPostRandom,
} from '@/services/api';
import {
  getSectionQueryParams,
  getTagQueryParams,
  getUserAvatar,
  toRelativeTime,
} from '@/lib/tool';
import Image from 'next/image';
import LoadPage from '@/app/[locale]/load/load';
import ErrorPage from '@/app/[locale]/error/error';
import FooterH5IcpPage from '@/app/[locale]/mobile/footerH5Icp';
import FooterH5Page from '@/app/[locale]/mobile/footerH5';
import SectionGroupHomeH5Page from '@/app/[locale]/mobile/home/sectionGroup';
import SectionHomeH5Page from '@/app/[locale]/mobile/home/section';
import { HomeH5PageContext } from '@/contexts/mobile/home';
import PostHomeH5Page from '@/app/[locale]/mobile/home/post';
import { useSearchParams } from 'next/navigation';
import type { ReadonlyURLSearchParams } from 'next/dist/client/components/navigation';
import useModal from '@/hooks/useModal';
import SearchModal from '@/app/[locale]/modal/search/search';
import useToast from 'hooks/useToast';
import { nanoid } from 'nanoid';

export default function HomeH5Page({ metadata }: { metadata: TMetadata }) {
  return (
    <>
      <Home metadata={metadata} />
      <FooterH5IcpPage metadata={metadata} />
      <FooterH5Page metadata={metadata} />
    </>
  );
}

const Home = ({ metadata }: { metadata: TMetadata }) => {
  const env = metadata.env;
  const searchParams = useSearchParams();
  const [currentTagItem, setCurrentTagItem] = useState<ITag | undefined>(
    getTagQueryParams(searchParams),
  );
  const [currentSectionItem, setCurrentSectionItem] = useState<
    ISectionClient | undefined
  >(getSectionQueryParams(searchParams));
  const [currentSectionGroupItem, setCurrentSectionGroupItem] = useState<
    ISectionGroup | undefined
  >(getSectionGroupQueryParams(searchParams));
  const [sectionPostParams, setSectionPostParams] = useState<IQueryParams>({});
  const [allPostParams, setAllPostParams] = useState<IQueryParams>({});
  const userQuery = useUser(metadata);
  const { show } = useToast();
  const [pages, setPages] = useState<IPost[]>(
    currentSectionItem
      ? (metadata.all['postsBySectionId']?.v as ISectionDetails)?.data
          ?.content ?? []
      : (metadata.all['posts'].v as IPagination<IPost>).content,
  );
  const [search, setSearch] = useState('');
  const { showModal } = useModal({
    metadata,
  });
  const [period, setPeriod] = useState(metadata.all['period'].v as string);

  const clientQueryAllSectionQuery = useQuery(
    metadata.all['sections'].k,
    async () => {
      return (await clientQueryAllSection()) as ISectionClient[];
    },
    {
      initialData: metadata.all['sections'].v as ISectionClient[],
    },
  );
  const queryPostRandomQuery = useQuery(
    metadata.all['randomPost'].k,
    async () => {
      return (await queryPostRandom()) as IPost[];
    },
    {
      initialData: metadata.all['randomPost'].v as IPost[],
    },
  );
  const clientQuerySectionDetailsByIdQuery = useInfiniteQuery(
    [
      '/forum',
      '/sections',
      '/client',
      currentSectionItem?.id,
      '/details',
      sectionPostParams,
      'infinite',
    ],
    async (context) => {
      return (await clientQuerySectionDetailsById({
        id: context.queryKey[3],
        query: {
          ...(context.queryKey[5] as IQueryParams),
          ...context.pageParam,
        },
      })) as ISectionDetails;
    },
    {
      enabled: !!currentSectionItem,
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (firstPage.data && firstPage.data.pageable.previous) {
          return {
            page: Math.max(firstPage.data.pageable.page - 1, 0),
          };
        }
      },
      getNextPageParam: (lastPage) => {
        if (lastPage.data && lastPage.data.pageable.next) {
          return {
            page: Math.min(
              lastPage.data.pageable.page + 1,
              lastPage.data.pageable.pages,
            ),
          };
        }
      },
      initialData: () => {
        if (metadata.all['postsBySectionId']) {
          return {
            pages: [metadata.all['postsBySectionId'].v as ISectionDetails],
            pageParams: [
              {
                page: Math.max(
                  ((metadata.all['postsBySectionId'].k[5] as IQueryParams)
                    .page ?? 1) - 1,
                  0,
                ),
              },
            ],
          };
        }
      },
    },
  );
  const clientQueryAllPostQuery = useInfiniteQuery(
    ['/forum', '/posts', '/client', allPostParams],
    async (context) => {
      return (await clientQueryAllPost({
        query: {
          ...(context.queryKey[3] as IQueryParams),
          ...context.pageParam,
        },
      })) as IPagination<IPost>;
    },
    {
      enabled: !currentSectionItem,
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (firstPage.pageable.previous) {
          return {
            page: Math.max(firstPage.pageable.page - 1, 0),
          };
        }
      },
      getNextPageParam: (lastPage) => {
        if (lastPage.pageable.next) {
          return {
            page: Math.min(lastPage.pageable.page + 1, lastPage.pageable.pages),
          };
        }
      },
      initialData: () => {
        if (metadata.all['posts']) {
          return {
            pages: [metadata.all['posts'].v as IPagination<IPost>],
            pageParams: [
              {
                page: Math.max(
                  ((metadata.all['posts'].k[3] as IQueryParams).page ?? 1) - 1,
                  0,
                ),
              },
            ],
          };
        }
      },
    },
  );

  useEffect(() => {
    if (currentSectionItem) {
      if (clientQuerySectionDetailsByIdQuery.data) {
        setPages(
          clientQuerySectionDetailsByIdQuery.data.pages
            .flatMap((item) => item.data?.content ?? [])
            .map((item) => {
              item._contentUpdatedOnText = toRelativeTime(
                item.contentUpdatedOn,
              );
              return item;
            }),
        );
      }
    } else {
      if (clientQueryAllPostQuery.data) {
        setPages(
          clientQueryAllPostQuery.data.pages
            .flatMap((item) => item.content)
            .map((item) => {
              item._contentUpdatedOnText = toRelativeTime(
                item.contentUpdatedOn,
              );
              return item;
            }),
        );
      }
    }
  }, [
    clientQueryAllPostQuery.data,
    clientQuerySectionDetailsByIdQuery.data,
    currentSectionItem,
  ]);

  async function onClickLoadMore() {
    try {
      if (currentSectionItem) {
        await clientQuerySectionDetailsByIdQuery.fetchNextPage();
      } else {
        await clientQueryAllPostQuery.fetchNextPage();
      }
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickSearch(
    e: FormEvent<HTMLFormElement> | MouseEvent<HTMLSpanElement>,
  ) {
    e.stopPropagation();
    e.preventDefault();

    const value = search.trim();
    if (!value) {
      show({
        type: 'DANGER',
        message: '搜索内容不能为空',
      });
      return;
    }
    if (value.length < 1) {
      show({
        type: 'DANGER',
        message: '暂无相关内容',
      });
      return;
    }

    const mid = nanoid();
    showModal({
      mid,
      centered: false,
      customContent: <SearchModal mid={mid} />,
    });
  }

  function onChangeSearch(e: ChangeEvent<HTMLInputElement>) {
    setSearch(e.target.value);
  }

  function getSectionGroupQueryParams(searchParams: ReadonlyURLSearchParams) {
    const sectionId = getSectionQueryParams(searchParams)?.id;
    if (sectionId) {
      const find = (metadata.all['sections'].v as ISectionClient[]).find(
        (item) => item.id === sectionId,
      );
      return find?.sectionGroup;
    }
  }

  if (
    userQuery.data &&
    clientQueryAllSectionQuery.data &&
    queryPostRandomQuery.data &&
    clientQueryAllPostQuery.data
  ) {
    const userData = userQuery.data;
    const sectionData = clientQueryAllSectionQuery.data;

    return (
      <HomeH5PageContext.Provider
        value={{
          metadata,
          currentSectionGroupItem,
          setCurrentSectionGroupItem,
          currentSectionItem,
          setCurrentSectionItem,
          currentTagItem,
          setCurrentTagItem,
        }}
      >
        <div className="col p-2">
          <div className="card rounded-5 border-0">
            <div className="card-body">
              <div className="vstack gap-4">
                <div className="d-flex gap-4 justify-content-between">
                  <div className="vstack flex-grow-1 gap-2">
                    <div className="user-select-none">{period}</div>
                    <div className="h4 mb-0">
                      {userData.user ? userData.user.alias : '游客用户'}
                    </div>
                  </div>
                  <Image
                    className="rounded-4"
                    src={getUserAvatar(userData.user, metadata).mediumAvatarUrl}
                    alt="avatar"
                    width={56}
                    height={56}
                    placeholder="blur"
                    blurDataURL={env.APP_BLUR_DATA_URL}
                  />
                </div>

                <form className="my-4" onSubmit={onClickSearch}>
                  <div className="input-group">
                    <span onClick={onClickSearch} className="input-group-text">
                      <i className="bi bi-search"></i>
                    </span>
                    <input
                      type="search"
                      className="form-control"
                      placeholder="请输入搜索内容"
                      aria-label="search"
                      aria-describedby="search"
                      name="search"
                      value={search}
                      onChange={onChangeSearch}
                    />
                  </div>
                </form>

                <SectionGroupHomeH5Page
                  items={
                    sectionData
                      .filter(
                        (item, index, array) =>
                          item.sectionGroup &&
                          array.findIndex(
                            (value) =>
                              value.sectionGroup!.id === item.sectionGroup!.id,
                          ) === index,
                      )
                      .map((item) => item.sectionGroup)
                      .sort((a, b) => a!.sort - b!.sort) as []
                  }
                />

                <SectionHomeH5Page
                  items={
                    (currentSectionGroupItem
                      ? sectionData.filter(
                          (item) =>
                            item.sectionGroup &&
                            item.sectionGroup.id === currentSectionGroupItem.id,
                        )
                      : sectionData) as []
                  }
                />

                <PostHomeH5Page
                  items={pages}
                  isInitialLoading={
                    clientQueryAllPostQuery.isInitialLoading ||
                    clientQuerySectionDetailsByIdQuery.isInitialLoading
                  }
                  isDisabled={
                    currentSectionItem
                      ? !clientQuerySectionDetailsByIdQuery.hasNextPage ||
                        clientQuerySectionDetailsByIdQuery.isFetchingNextPage
                      : !clientQueryAllPostQuery.hasNextPage ||
                        clientQueryAllPostQuery.isFetchingNextPage
                  }
                  isFetchingNextPage={
                    currentSectionItem
                      ? clientQuerySectionDetailsByIdQuery.isFetchingNextPage
                      : clientQueryAllPostQuery.isFetchingNextPage
                  }
                  onClickLoadMore={onClickLoadMore}
                />
              </div>
            </div>
          </div>
        </div>
      </HomeH5PageContext.Provider>
    );
  }

  if (
    userQuery.error ||
    clientQueryAllSectionQuery.error ||
    queryPostRandomQuery.error ||
    clientQuerySectionDetailsByIdQuery.error ||
    clientQueryAllPostQuery.error
  ) {
    return (
      <ErrorPage
        error={
          userQuery.error ||
          clientQueryAllSectionQuery.error ||
          queryPostRandomQuery.error ||
          clientQuerySectionDetailsByIdQuery.error ||
          clientQueryAllPostQuery.error
        }
      />
    );
  }

  return <LoadPage />;
};
